{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "personal-pride",
   "metadata": {},
   "source": [
    "# 纠缠蒸馏 -- BBPSSW 协议\n",
    "\n",
    "\n",
    "<em> Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. All Rights Reserved. </em>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "consistent-hungary",
   "metadata": {},
   "source": [
    "## 概述\n",
    "\n",
    "量子纠缠在量子通信，量子计算和其他许多量子技术中起着至关重要的作用。因此，如果我们想在这些领域构建实际应用，探测、传输和分发量子纠缠是必不可少的任务。但是在实际操作中，误差是不可避免的。这些误差可能来自于生产纠缠设备的缺陷，也可能是传输量子纠缠时的信道噪声。随着传输距离的增加，噪声会导致纠缠资源的不断减少。而纠缠蒸馏（entanglement distillation）这项技术的开发目的正是为了补偿各种噪声引起的纠缠资源消耗。基本的实现原理为通过操作多对含噪的纠缠态将纠缠资源集中在其中一对纠缠态上，并使之尽可能的接近**最大纠缠态**（qubit 情况下，通常是大家熟知的贝尔态）。从这个意义上讲，也可以将纠缠蒸馏看作一种提纯/纠错协议。此过程通常由 Alice 和 Bob 两个远程参与方执行，由于双方在空间上会相隔一定的距离，因此仅允许本地操作和经典通信（LOCC）[1]。纠缠蒸馏的概念最早由 C. H. Bennett 等人于 1996 年提出 [2]，最初的协议按照作者们的首字母简写为 **BBPSSW 协议**。本教程主要介绍纠缠蒸馏的基本概念，具体的 BBPSSW 协议流程，以及如何通过量桨模拟该协议。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "mighty-model",
   "metadata": {},
   "source": [
    "### 贝尔态\n",
    "\n",
    "量子信息处理中的诸多协议都使用了贝尔态，比如量子隐形传态 [3]，超密编码 [4] 和基于贝尔定理的量子密码学 [5]。如此广阔的应用范围使四个贝尔态成为尤其重要的研究课题。它们通常用定义为：\n",
    "\n",
    "$$\n",
    "\\begin{align*}\n",
    "|\\Phi^{\\pm}\\rangle_{AB} &= \\frac{1}{\\sqrt{2}}(|0\\rangle_A\\otimes|0\\rangle_B \\pm |1\\rangle_A\\otimes|1\\rangle_B), \\\\\n",
    "|\\Psi^{\\pm}\\rangle_{AB} &= \\frac{1}{\\sqrt{2}}(|0\\rangle_A\\otimes|1\\rangle_B \\pm |1\\rangle_A\\otimes|0\\rangle_B). \n",
    "\\tag{1}\n",
    "\\end{align*}\n",
    "$$\n",
    "\n",
    "其中 $A$（Alice）持有一个量子比特，而 $B$（Bob）持有另一个量子比特。注意到这些纯态不能分解为两个纯态的张量积 $| \\varphi \\rangle_A \\otimes | \\psi \\rangle_B$。 **注释：这是纯态表示下纠缠态的重要特征。密度矩阵的表示下关于量子纠缠的定性条件会更为复杂，这里我们不做进一步讨论。**\n",
    "\n",
    "贝尔态还有一个有趣的特点，如果对其中一个子系统 $A$ 求偏迹，那么剩下子系统 $B$ 的密度矩阵就会变成 $I / 2$。举个例子，让我们一起观察贝尔态 $| \\Phi ^ {+} \\rangle_ {AB}$\n",
    "\n",
    "$$\n",
    "\\begin{align*}\n",
    "\\rho_B &\\equiv \\text{tr}_A(\\Phi^{+}_{AB}), \\\\\n",
    "& = \\text{tr}_A(|\\Phi^{+}\\rangle\\langle\\Phi^+|_{AB}), \\\\\n",
    "& = \\frac{1}{2}\\text{tr}_A\\big(|00\\rangle\\langle00|+|00\\rangle\\langle11|+|11\\rangle\\langle00|+|11\\rangle\\langle11|\\big),\\\\\n",
    "& = \\frac{1}{2} \\big(\\text{tr}_A(|0\\rangle\\langle0|_A)\\cdot|0\\rangle\\langle0|_B + \\text{tr}_A(|0\\rangle\\langle1|_A)\\cdot|0\\rangle\\langle1|_B  \\\\\n",
    "& \\quad\\quad + \\text{tr}_A(|1\\rangle\\langle0|_A) \\cdot|1\\rangle\\langle0|_B+\n",
    "\\text{tr}_A(|1\\rangle\\langle1|_A)\\cdot|1\\rangle\\langle1|_B \\big), \\\\\n",
    "& = \\frac{1}{2} (|0\\rangle\\langle0|_B + |1\\rangle\\langle1|_B) = \\frac{1}{2} I.\n",
    "\\tag{2}\n",
    "\\end{align*}\n",
    "$$\n",
    "\n",
    "**注释：** 这是因为纠缠的量子比特对之间存在非经典的相关性，我们无法使用有关子系统的部分信息来描述整个系统。\n",
    "\n",
    "在量桨中，我们可以通过调用函数 `bell_state()` 便捷创建贝尔态 $ \\Phi ^ {+} _ {AB} = |\\Phi^{+}\\rangle\\langle\\Phi^+|_{AB}$（密度矩阵表示）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "bearing-millennium",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-02-23T09:09:21.025275Z",
     "start_time": "2021-02-23T09:09:20.598689Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "生成的量子态 Phi  = \n",
      " [[0.5+0.j 0. +0.j 0. +0.j 0.5+0.j]\n",
      " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n",
      " [0. +0.j 0. +0.j 0. +0.j 0. +0.j]\n",
      " [0.5+0.j 0. +0.j 0. +0.j 0.5+0.j]]\n"
     ]
    }
   ],
   "source": [
    "from paddle_quantum.state import bell_state\n",
    "N = 2     # 指定量子比特数量\n",
    "rho = bell_state(N)\n",
    "print(\"生成的量子态 Phi  = \\n\", rho)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "stuck-ballot",
   "metadata": {},
   "source": [
    "### 量化纠缠资源\n",
    "\n",
    "在定性地了解了量子纠缠之后，我们希望能将读者对纠缠的理解提升到一个量化的水平。 首先，我们需要指出上述量子通信协议的有效性，比如量子隐形传态和超密编码，都取决于**纠缠资源的量**，或者说有多少纠缠资源可以被用作为 \"燃料\"去消耗。按照量子信息学界的惯例，**negativity** $ \\mathcal {N}(\\rho)$ 和 **logarithmic negativity** $ E_{N}(\\rho)$ 是公认的可用于量化纠缠资源的指标 [6]。具体的定义如下，\n",
    "\n",
    "$$\n",
    "\\mathcal{N}(\\rho) \\equiv \\frac{||\\rho^{T_B}||_1-1}{2},\n",
    "\\tag{3}\n",
    "$$\n",
    "\n",
    "以及\n",
    "\n",
    "$$\n",
    "E_{N}(\\rho) \\equiv \\text{log}_2 ||\\rho^{T_B}||_1,\n",
    "\\tag{4}\n",
    "$$\n",
    "\n",
    "其中 $ T_B $ 代表相对于子系统 $ B $ 的部分转置 （partial transpose）操作，可以定义为 [7]，\n",
    "\n",
    "$$\n",
    "\\rho_{A B}^{T_{B}}:=(I \\otimes T)(\\rho_{A B})=\\sum_{i, j}(I_{A} \\otimes|i\\rangle\\langle j|_{B}) \\rho_{A B}(I_{A} \\otimes|i\\rangle\\langle j|_{B}).\n",
    "\\tag{5}\n",
    "$$\n",
    "\n",
    "\n",
    "$||\\cdot ||_ 1$ 表示迹范数，$\\{|i\\rangle_B\\}$ 是 $B$ 系统上的一组基。上述两个指标间的联系为 $E_{N}(\\rho) = \\text{log}_2 (2\\mathcal{N}(\\rho)+1)$。 它们都与 PPT 的可分离性指标有关。\n",
    "> *如果密度矩阵进行部分转置后没有负特征值（即半正定的），则称其具有 positive partial transpose, PPT。 否则，称为 negative partial transpose, NPT。*\n",
    "\n",
    "\n",
    "我们引入此类度量标准的原因不仅是希望帮助更好地理解量子纠缠，更进一步希望这些指标可以指导我们进行蒸馏协议的研发。**注释：所有 PPT 量子态一般被认为处于弱纠缠，是不可蒸馏的**。 这意味着满足 PPT 条件的量子态都无法作为输入态来进行纠缠蒸馏。因此，在执行蒸馏方案之前，检查初始量子态是否满足该条件是非常必要的。以上提及的这些概念都通过调用量桨中的函数 `negativity()`，`logarithmic_negativity()`， `partial_transpose()`，还有 `is_ppt()`。\n",
    "\n",
    "**注释：** 更多关于定性认识量子纠缠的讨论，请参考这篇综述文章[8]。\n",
    "\n",
    "在介绍了许多新概念之后，我们提供了一个具体示例。对于特定的贝尔态 $|\\Phi^{+}\\rangle_{AB}$，我们有\n",
    "\n",
    "$$\n",
    "\\begin{align*}\n",
    "\\rho^{T_{B}} &= \\frac{1}{2}\n",
    "\\big(|00\\rangle\\langle00|+|01\\rangle\\langle10|+|10\\rangle\\langle01|+|11\\rangle\\langle11|\\big),\\\\\n",
    "& = \\frac{1}{2}\n",
    "\\begin{bmatrix}\n",
    "1 & 0 & 0 & 0\\\\\n",
    "0 & 0 & 1 & 0\\\\\n",
    "0 & 1 & 0 & 0\\\\\n",
    "0 & 0 & 0 & 1\n",
    "\\end{bmatrix}\n",
    "\\tag{6}\n",
    "\\end{align*}\n",
    "$$\n",
    "\n",
    "其含有负的特征值 $\\lambda_{-}(\\rho^{T_{B}}) = -1/2$ 并可以算出 $E_{N}(\\rho) = 1$。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "unique-class",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-02-23T09:09:26.267474Z",
     "start_time": "2021-02-23T09:09:23.986839Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "部分转置后的量子态为\n",
      " [[0.5+0.j 0. +0.j 0. +0.j 0. +0.j]\n",
      " [0. +0.j 0. +0.j 0.5+0.j 0. +0.j]\n",
      " [0. +0.j 0.5+0.j 0. +0.j 0. +0.j]\n",
      " [0. +0.j 0. +0.j 0. +0.j 0.5+0.j]]\n",
      "With negativity = 0.5 and logarithmic_negativity = 1.0\n",
      "输入态满足 PPT 条件因此无法被蒸馏? False\n"
     ]
    }
   ],
   "source": [
    "from paddle_quantum.state import bell_state\n",
    "from paddle_quantum.utils import negativity, logarithmic_negativity, partial_transpose, is_ppt\n",
    "\n",
    "input_state = bell_state(2)\n",
    "transposed_state = partial_transpose(input_state, 2)   # 2 代表量子比特数量\n",
    "print(\"部分转置后的量子态为\\n\", transposed_state)\n",
    "\n",
    "neg = negativity(input_state)\n",
    "log_neg = logarithmic_negativity(input_state)\n",
    "print(\"With negativity =\", neg,\"and logarithmic_negativity =\", log_neg)\n",
    "print(\"输入态满足 PPT 条件因此无法被蒸馏?\", is_ppt(input_state))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "needed-arkansas",
   "metadata": {},
   "source": [
    "在纠缠蒸馏方案中，我们通常使用蒸馏后的输出态 $\\rho_{out}$ 和贝尔态 $|\\Phi^+\\rangle$ 之间的**保真度（state fidelity）**$F$ 来量化蒸馏方案的性能，其中\n",
    "\n",
    "$$\n",
    "F(\\rho_{out}, \\Phi^+) \\equiv \\langle \\Phi^+|\\rho_{out}|\\Phi^+\\rangle.\n",
    "\\tag{7}\n",
    "$$\n",
    "\n",
    "之前提到过蒸馏任务中的目标是获得高保真度的量子态 $\\rho_{out}$，所以选择保真度作为度量标准来量化当前量子态和目标态之间的距离是合理的。我们可以调用量桨中函数 `state_fidelity(rho, sigma)` 来计算保真度，\n",
    "\n",
    "$$\n",
    "F_s(\\rho,\\sigma) \\equiv \\text{tr}\\big( \\sqrt{\\sqrt{\\rho}\\sigma \\sqrt{\\rho}} \\big).\n",
    "\\tag{8}\n",
    "$$\n",
    "\n",
    "**注释：** 这两个保真度的公式的关系为 $F=F_s^2$ 。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "assigned-laptop",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-02-23T09:09:28.053216Z",
     "start_time": "2021-02-23T09:09:28.045377Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "两个态的保真度是:\n",
      "F= 0.7750000000000004\n"
     ]
    }
   ],
   "source": [
    "from paddle_quantum.state import bell_state, isotropic_state\n",
    "from paddle_quantum.utils import state_fidelity\n",
    "\n",
    "F = state_fidelity(bell_state(2), isotropic_state(2, 0.7))\n",
    "print(\"两个态的保真度是:\\nF=\", F**2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "indian-brooks",
   "metadata": {},
   "source": [
    "经过以上准备，我们可以开始介绍 BBPSSW 协议。\n",
    "\n",
    "## BBPSSW 协议\n",
    "\n",
    "BBPSSW 协议将两份相同的两方量子态 $\\rho_{in}$ 蒸馏成输出态 $\\rho_{out}$，一份具有更高的保真度 $ F $（更接近贝尔态 $|\\Phi^+\\rangle$）的两方量子态。值得注意的是，BBPSSW 主要用于蒸馏 **isotropic 态**（也称为 Werner 态），由 $|\\Phi^+\\rangle$ 和完全混合态（白噪声）$I/4$ 组成。\n",
    "\n",
    "$$\n",
    "\\rho_{\\text{iso}}(p) = p\\lvert\\Phi^+\\rangle \\langle\\Phi^+\\rvert + (1-p)\\frac{I}{4}, \\quad p \\in [0,1]\n",
    "\\tag{9}\n",
    "$$\n",
    "\n",
    "此量子态在 $p \\leq 1/3$ 时满足 PPT 条件，因此不可蒸馏。\n",
    "\n",
    "BBPSSW 蒸馏协议由两个远程参与方 $ A $（Alice）和 $ B $（Bob）执行。它们共享两份量子对 $ \\rho_{A_0B_0} $ 和 $ \\rho_{A_1B_1} $。每对的初始态均为 $ \\rho_ {in} = \\rho _ {\\text {iso}}(p)$。Alice 拥有两个量子比特 $ A_0，A_1 $，Bob 也拥有两个量子比特 $ B_0，B_1 $。通过这些初始设置，Alice 和 Bob 需要实现以下流程：\n",
    "\n",
    "1. Alice 和 Bob 先选择任意一对量子比特，**这对量子比特将作为最终的输出比特**。这里假设他们选择了 $A_0$ 和 $B_0$。\n",
    "2. Alice 和 Bob 对他们手中的量子比特施加受控非门（CNOT 门）。这里, $A_0$ 和 $B_0$ 作为控制比特，$A_1$ 和 $B_1$ 作为目标比特。\n",
    "3. 接下来双方分别对 $A_1$ 和 $B_1$ 进行测量，并通过**经典通讯**来交换他们的测量结果 $m_{A_1}, m_{B_1}$。\n",
    "4. 如果 Alice 和 Bob 的结果一致（00或11），那么他们可以宣布本次蒸馏过程成功，同时将 $A_0$ 和 $B_0$ 作为输出比特，输出态为 $\\rho_{out}$。相反，如果他们的测量结果不一致（01或10），那么本次蒸馏过程失败，丢弃量子比特 $A_0$ 和 $B_0$。无论蒸馏成功与否，测量之后的量子比特 $A_1,B_1$ 都不会再被使用。\n",
    "\n",
    "\n",
    "<center><img src=\"figures/distillation-fig-BBPSSW.png\" height=\"200\" width=\"400\"></center>\n",
    "<div style=\"text-align:center\">图 1: BBPSSW 纠缠蒸馏协议的示意图 </div>\n",
    "\n",
    "\n",
    "**注释:** 纠缠蒸馏方案是概率性的，并非每次都能成功。因此，量化蒸馏方案性能的另一个指标是**成功概率$ p_ {succ} $**。实际的蒸馏协议总是在输出态的保真度 $F' = F(\\rho_{out},\\Phi^+)$ 和 $p_{succ}$ 之间进行权衡的。 从理论上讲，BBPSSW 协议的这两个特定指标公式如下：\n",
    "$$\n",
    "F^{\\prime}=\\frac{F^2 + \\frac{1}{9}(1-F)^2}{F^2 + \\frac{2}{3}F(1-F) + \\frac{5}{9}(1-F)^2},\n",
    "\\tag{10}\n",
    "$$\n",
    "\n",
    "初始态的保真度为 $F(\\rho_{in},\\Phi^+) = (1+3p)/4$。成功的概率为，\n",
    "\n",
    "$$\n",
    "p_{\\text {succ }}=F^{2} + \\frac{2}{3}F(1-F) + \\frac{5}{9}(1-F)^2.\n",
    "\\tag{11}\n",
    "$$\n",
    "\n",
    "在下一节中，我们将介绍如何使用量桨模拟 BBPSSW 协议。\n",
    "\n",
    "**注释:** 如果输入态不是 isotropic 态 ，则可以通过概率性的旋转操作将其去极化（depolarize）为 isotropic 态。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "noted-elimination",
   "metadata": {},
   "source": [
    "## Paddle Quantum 代码实现\n",
    "\n",
    "首先，我们需要导入所有依赖包："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "inside-vulnerability",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-02-23T09:09:36.454093Z",
     "start_time": "2021-02-23T09:09:36.069131Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from paddle_quantum.locc import LoccNet\n",
    "from paddle import matmul, trace\n",
    "import paddle\n",
    "from paddle_quantum.state import bell_state, isotropic_state\n",
    "from paddle_quantum.utils import logarithmic_negativity, is_ppt"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "appropriate-smith",
   "metadata": {},
   "source": [
    "为了方便起见，我们在此处计算 BBPSSW 的度量，然后与模拟结果进行比较。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "considerable-premises",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-02-23T09:09:38.315327Z",
     "start_time": "2021-02-23T09:09:38.302105Z"
    }
   },
   "outputs": [],
   "source": [
    "def BBPSSW_metrics(p):\n",
    "    \"\"\"\n",
    "    返回输出态的保真度以及 BBPSSW 协议的成功率。\n",
    "    \"\"\"\n",
    "    F_in = (1+3*p)/4\n",
    "    p_succ = F_in**2 + 2*F_in*(1-F_in)/3+ 5*(1-F_in)**2/9\n",
    "    F_out = (F_in**2 + (1-F_in)**2/9)/p_succ\n",
    " \n",
    "    return F_in, F_out, p_succ"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "sudden-interstate",
   "metadata": {},
   "source": [
    "在我们的示例中，输入态是 Isotropic 态，其中 $ p = 0.7 $，也就是说\n",
    "\n",
    "$$\n",
    "\\rho_{in} = \\rho_{\\text{iso}}(0.7)= 0.7\\lvert\\Phi^+\\rangle \\langle\\Phi^+\\rvert + 0.075 I.\n",
    "\\tag{12}\n",
    "$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "sized-rover",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-02-23T09:09:41.248379Z",
     "start_time": "2021-02-23T09:09:41.226807Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "输入态的保真度是: 0.7749999999999999\n",
      "输出态的保真度是: 0.8137583892617447\n",
      "成功率是: 0.745\n",
      "输入态满足 PPT 条件因此无法被蒸馏? False\n"
     ]
    }
   ],
   "source": [
    "p = 0.7\n",
    "F_in, F_out, p_succ = BBPSSW_metrics(p)\n",
    "print(\"输入态的保真度是:\", F_in)\n",
    "print(\"输出态的保真度是:\", F_out)\n",
    "print(\"成功率是:\", p_succ)\n",
    "print(\"输入态满足 PPT 条件因此无法被蒸馏?\", is_ppt(isotropic_state(2, p)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "increasing-national",
   "metadata": {},
   "source": [
    "然后，我们模拟 BBPSSW 协议，并检查结果是否与理论相符。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "motivated-association",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-02-23T09:09:44.342242Z",
     "start_time": "2021-02-23T09:09:44.322978Z"
    }
   },
   "outputs": [],
   "source": [
    "class LOCC(LoccNet):\n",
    "    def __init__(self):\n",
    "        super(LOCC, self).__init__()\n",
    "        \n",
    "        # 添加第一个参与方 Alice\n",
    "        # 第一个参数 2 代表着 Alice 手里有几个量子比特\n",
    "        # 第二个参数代表着参与方的名字\n",
    "        self.add_new_party(2, party_name='Alice')\n",
    "        \n",
    "        # 添加第二个参与方 Bob\n",
    "        # 第一个参数 2 代表着 Bob 手里有几个量子比特\n",
    "        # 第二个参数代表着参与方的名字\n",
    "        self.add_new_party(2, party_name='Bob')\n",
    "        \n",
    "        # 定义输入量子态 rho_in\n",
    "        _state = paddle.to_tensor(isotropic_state(2, p))\n",
    "        \n",
    "        # ('Alice', 0) 代表 Alice 的第一个量子比特 A0\n",
    "        # ('Bob', 0) 代表 Bob 的第一个量子比特 B0\n",
    "        self.set_init_state(_state, [('Alice', 0), ('Bob', 0)]) \n",
    "        \n",
    "        # ('Alice', 1) 代表 Alice 的第二个量子比特 A1\n",
    "        # ('Bob', 1) 代表 Bob 的第二个量子比特 B1\n",
    "        self.set_init_state(_state, [('Alice', 1), ('Bob', 1)])  \n",
    "        \n",
    "    def BBPSSW(self):\n",
    "        status = self.init_status\n",
    "        \n",
    "        # 创建 Alice 的局部操作\n",
    "        cir1 = self.create_ansatz('Alice')\n",
    "        cir1.cnot([0, 1])\n",
    "\n",
    "        # 创建 Bob 的局部操作\n",
    "        cir2 = self.create_ansatz('Bob')\n",
    "        cir2.cnot([0, 1])\n",
    "    \n",
    "        # 运行电路\n",
    "        status = cir1.run(status)\n",
    "        status_mid = cir2.run(status)\n",
    "        \n",
    "        # ('Alice', 1) 代表测量 Alice 的第二个量子比特 A1\n",
    "        # ('Bob', 1) 代表测量 Bob 的第二个量子比特 B1\n",
    "        # ['00','11'] 代表着成功的蒸馏实验所需条件\n",
    "        # Alice 和 Bob 同时测得 '00' or '11'\n",
    "        status_mid = self.measure(status_mid, [('Alice', 1), ('Bob', 1)], [\"00\", \"11\"])\n",
    "        \n",
    "        # 取偏迹除去测量后的量子比特 A1&B1\n",
    "        # 把 Alice 还有 Bob 的第一个量子比特 A0&B0 作为寄存器\n",
    "        status_fin = self.partial_state(status_mid, [('Alice', 0), ('Bob', 0)])\n",
    "        \n",
    "        return status_fin"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "enormous-workplace",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-02-23T09:10:17.568446Z",
     "start_time": "2021-02-23T09:10:17.205178Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "输入态的保真度是: 0.77500\n",
      "蒸馏后的量子态保真度是: 0.81376\n",
      "蒸馏成功的概率是: 74.500%\n",
      "========================================================\n",
      "输出态是:\n",
      " [[0.48489933+0.j 0.        +0.j 0.        +0.j 0.32885906+0.j]\n",
      " [0.        +0.j 0.01510067+0.j 0.        +0.j 0.        +0.j]\n",
      " [0.        +0.j 0.        +0.j 0.01510067+0.j 0.        +0.j]\n",
      " [0.32885906+0.j 0.        +0.j 0.        +0.j 0.48489933+0.j]]\n",
      "初始 logarithmic negativity 是: 0.6322682154995127\n",
      "蒸馏后 logarithmic negativity 是: 0.7026724166123284\n"
     ]
    }
   ],
   "source": [
    "# 运行 BBPSSW 协议\n",
    "status_fin = LOCC().BBPSSW()\n",
    "\n",
    "# 计算保真度\n",
    "target_state = paddle.to_tensor(bell_state(2))\n",
    "fidelity = 0\n",
    "for status in status_fin:\n",
    "    fidelity += paddle.real(trace(matmul(target_state, status.state)))\n",
    "fidelity /= len(status_fin)\n",
    "\n",
    "# 计算成功概率\n",
    "suc_rate = sum([status.prob for status in status_fin])\n",
    "fidelity_in,_,_ = BBPSSW_metrics(p)\n",
    "\n",
    "# 输出模拟结果\n",
    "print(f\"输入态的保真度是: {fidelity_in:.5f}\")\n",
    "print(f\"蒸馏后的量子态保真度是: {fidelity.numpy()[0]:.5f}\")\n",
    "print(f\"蒸馏成功的概率是: {suc_rate.numpy()[0]:#.3%}\")\n",
    "\n",
    "# 打印输出态\n",
    "rho_out = status_fin[0].state.numpy()\n",
    "print(\"========================================================\")\n",
    "print(f\"输出态是:\\n {rho_out}\")\n",
    "print(f\"初始 logarithmic negativity 是: {logarithmic_negativity(isotropic_state(2,p))}\")\n",
    "print(f\"蒸馏后 logarithmic negativity 是: {logarithmic_negativity(rho_out)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "progressive-church",
   "metadata": {},
   "source": [
    "## 结论\n",
    "\n",
    "可以看到，模拟结果与理论预测完全吻合。 通过 BBPSSW 协议，我们可以从两个低保真度的纠缠态中提取具有更高保真度的纠缠态。\n",
    "\n",
    "**优点**\n",
    "- 操作很简单，仅需要 CNOT 门。\n",
    "- 成功概率高。\n",
    "\n",
    "**缺点**\n",
    "- 对输入态类型的严格要求。 要求 Isotropic 态。\n",
    "- 可拓展性较差，无法直接扩展到多个拷贝的情况。\n",
    "\n",
    "我们建议感兴趣的读者可以接着浏览以下教程学习 [如何通过 LOCCNet 设计全新的纠缠蒸馏方案](./EntanglementDistillation_LOCCNET_CN.ipynb)。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "appropriate-postage",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## 参考文献\n",
    "\n",
    "[1] Chitambar, Eric, et al. \"Everything you always wanted to know about LOCC (but were afraid to ask).\" [Communications in Mathematical Physics 328.1 (2014): 303-326.](https://link.springer.com/article/10.1007/s00220-014-1953-9)\n",
    "\n",
    "[2] Bennett, Charles H., et al. \"Purification of noisy entanglement and faithful teleportation via noisy channels.\" [Physical Review Letters 76.5 (1996): 722.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.76.722)\n",
    "\n",
    "[3] Bennett, Charles H., et al. \"Teleporting an unknown quantum state via dual classical and Einstein-Podolsky-Rosen channels.\" [Physical Review Letters 70.13 (1993): 1895.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.70.1895)\n",
    "\n",
    "[4] Bennett, Charles H., and Stephen J. Wiesner. \"Communication via one-and two-particle operators on Einstein-Podolsky-Rosen states.\" [Physical Review Letters 69.20 (1992): 2881.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.69.2881)\n",
    "\n",
    "[5] Ekert, Artur K. \"Quantum cryptography based on Bell’s theorem.\" [Physical Review Letters 67.6 (1991): 661.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.67.661)\n",
    "\n",
    "[6] Życzkowski, Karol, et al. \"Volume of the set of separable states.\" [Physical Review A 58.2 (1998): 883.](https://journals.aps.org/pra/abstract/10.1103/PhysRevA.58.883)\n",
    "\n",
    "[7] Peres, Asher. \"Separability criterion for density matrices.\" [Physical Review Letters 77.8 (1996): 1413.](https://journals.aps.org/prl/abstract/10.1103/PhysRevLett.77.1413)\n",
    "\n",
    "[8] Gühne, Otfried, and Géza Tóth. \"Entanglement detection.\" [Physics Reports 474.1-6 (2009): 1-75.](https://www.sciencedirect.com/science/article/abs/pii/S0370157309000623)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.10"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
